繼昨天的鼠標浮動飛鏢,以及計算飛鏢目的地後,我們今天要來讓飛鏢具有飛行的動畫效果,那就開始吧!
打開昨天設置飛鏢目的地的 更新顯示物件,裡面有一個 設定補間動畫,可以利用 Easing 函數,讓我們將時間以一個數學式關聯到物件的某個屬性上,藉此來產生動畫效果,聽起來好像很複雜,先來看看動作內的設定如何。
補間動畫也算是一種物件,所以同樣可以為其命名一個 ID,其他則是代表動畫的效果以及動畫時間。
目前 補間方式 的所有種類如下:
而 補間時機 則有:
其中補間方式除了 Linear 以外,其他都可以與補間時機搭配出不同的動畫效果,因為 Linear 就只是一條直線而已,而關於 Easing 函數詳細的原理我就不多嘴了,因為我頂多只能說是會用,要能夠講解就不太有把握了,所以下面這裡我提供了一些推薦的連結,以及 CG 使用 Easing 函數的原始函示庫給各位參考。
小哈的教學影片:數學妹子與遊戲漢子的相遇: (科普)Easing函式將遊戲可愛化了
Easing 函數小抄:easings.net
Easing 函數的函式庫:tween.js
各位可以自行嘗試各種不同的補間方式和時機,來決定自己想要的動畫過程,我個人是選擇 Quintic Out(五次方淡出),動畫時間則設定為 2000 毫秒,這樣飛鏢飛出的速度感我覺得很棒,動畫 ID 則不用管,因為我們不會需要讀取到這個物件,設定好後儲存動作。
接下來由於 tap_x
、tap_y
這兩個變數的用途已經結束了,所以我們要來將其刪除,新增兩個動作 刪除全域變數,各自填入這兩個變數名稱即可。
變數刪除後,接下來我們要等到飛鏢停止運動後將飛鏢移除,不過由於五次方淡出的關係,所以飛鏢大概在 1000 毫秒之後就沒什麼動力了,如果不是選擇五次方淡出的話,可能就要另外測試適合的等待時間了,總之我們新增動作 等待,時間設為 1000 毫秒,接著新增動作 移除物件,物件ID 選擇 dart*
用來將其移除。
設定好後就可以測試遊戲看看了,這時應該就可以正常的投擲飛鏢了,且飛鏢在即將停止前就會被移除,是不是很酷呢?
雖然可以投擲飛鏢了,但飛鏢一點轉動的痕跡都沒有,看起來很無趣,所以我們要來讓飛鏢飛出時會跟著轉動。
還記得我們前天介紹轉動飛鏢時所說的嗎?要設置飛鏢的轉動必須單獨調整本體與陰影的角度,因此我們要來重複這個步驟。
新增動作 更新顯示物件,先選擇 dart*.dart_clip*
,由於這次飛鏢的轉動動畫是需要 補間動畫 來完成,所以我們要將其設定成和飛出飛鏢的補間動畫相同,接著勾選 設定旋轉角度,然後就是 旋轉角度 究竟該怎麼決定了。
旋轉角度預設是 {this.rotationDeg}
,代表當前物件自身的角度,所以若是要讓其旋轉,只要以此為基礎,加或減其他數值即可,例如 {this.rotationDeg} + 10
就是讓其順時針轉 10 度,反之負數就是逆時針。
數學還不錯的人會發現,在這裡角度的方向與一般數學所學到的不同,因為一般數學中的座標平面,向上是 y 會越大,向下則越小,所以角度從 0 開始增加時也是向上移動(逆時針),但在電腦的世界中,原點 (0,0) 是畫面的左上角,往右同樣是 x 越大,但往下就變成 y 越大了,因此在這裡角度的變化,從 0 開始增加就會變成向下移動(順時針)。
我們昨天不是已經算出飛鏢飛出的距離了嗎?由於我們的動畫時間是固定的,因此距離越大,代表速度越快,所以某方面來說這個距離也可以代表飛行速度的意思,飛行速度越快,轉動的速度也就越快。
因此我們可以把昨天的算式拿來用,變成如下的算式:
{this.rotationDeg} + sqrt(pow({mouse.x} - {tap_x}, 2) + pow({mouse.y} - {tap_y}, 2))
但只是單純加上鼠標距離的話,轉動速度看起來會過慢,因此與昨天的移動距離一樣,要乘以一個倍數,我自己是將其乘以 2,所以最終的算式如下:
{this.rotationDeg} + sqrt(pow({mouse.x} - {tap_x}, 2) + pow({mouse.y} - {tap_y}, 2)) * 2
完成後可以複製該動作,並將物件 ID 改成 dart*.dart_shadow*
後儲存,然後將剛剛新增的兩個更新顯示物件移到刪除全域變數的上方,不然變數被刪掉後才執行就沒用了。
接著再測試一次,可以看到飛鏢被投擲後已經會自體旋轉了,但此時我們還有一個小細節要添加,那就是如果滑鼠停留在飛鏢上,不斷的點擊飛鏢,由於距離為 0 的關係,此時就會一直生出不會動的飛鏢,為了避免這個問題,我們要來新增一項檢查,那就是判斷玩家的滑鼠在按下之後,鼠標是否有稍微移動過。
最簡單的判斷方法就是使用 比較數字 來比較距離,如果移動的距離 > 50 就算通過,這個機制的意思就是當力道太小時,飛鏢會沒辦法投擲,至於距離的計算公式相信不用多說了,我們剛剛已經使用過了,所以設定結果就是 sqrt(pow({mouse.x} - {tap_x}, 2) + pow({mouse.y} - {tap_y}, 2)) > 50
,完成後儲存。
還沒完,由於這個檢查的關係,造成我們現在按下飛鏢,放開後可能不會執行事件的緣故,導致儲存滑鼠座標的變數不會被移除,因此這時我們只要輕點一下飛鏢,再點一下上方的空地,就可以投擲飛鏢了,就不是按住飛鏢拖曳後再放開了,所以這個部分也要解決。
這時就是否則觸發事件登場的時候了,當距離檢查不通過時,就觸發其他事件來移除變數,因此我們先新增一個事件 飛鏢投擲失敗,將其設定為 參考事件,並將上方的兩個 刪除全域變數 複製後拖曳下來,事件就設定完了。
回到剛剛的 比較數字 中,將 否則觸發事件ID 設定為 飛鏢投擲失敗 後儲存檢查,如此一來就可以避免上述情況的發生了。
最終 放開飛鏢 事件就如上圖所示,此時最後測試一下,投擲飛鏢的部分已經很完整了,唯一美中不足的地方可能就是飛鏢不會落地,兩年前的我有讓飛鏢落地,但我們已經花很多時間在飛鏢身上了,所以就先到此為止。
最後還有另外一點,在投擲飛鏢後,如果是電腦端的話,應該會發現投擲出去的飛鏢會飛出舞台,繼續在漆黑的深淵中飛行,這似乎有點奇怪,所以明天我們會介紹如何限制物件只顯示在舞台中的方法。
今天稍微介紹了補間動畫的使用,並完成了飛鏢的飛行、旋轉動畫,還在投擲時加入的最小力道的判斷,飛鏢的部分總算是告一段落了,明天我們要來實作標靶的部分,這應該就比較簡單了,另外還有剛剛提到的,不讓顯示物件出現在舞台以外的地方的方法。